/**
 * @Author: Your name
 * @Date:   2023-02-09 14:58:22
 * @Last Modified by:   Your name
 * @Last Modified time: 2023-02-27 18:53:50
 */

const express = require("express");
const encryption = require("../utils/encryption");
const child_process = require("child_process");
const fs = require("fs");
const moment = require("moment");
const WXBizMsgCrypt = require("wxmsgcrypt");
const { XMLParser, XMLBuilder, XMLValidator} = require("fast-xml-parser");

const rootRouter = express.Router();

const AESKey = "saNzEG8t95svT6J640AkgzOJ8K4dXDDGFcVdPFM5MbM";
const token = "abcdefg123456789";
const appid = "wx3ea51e40d566d4a0";
const fxp = new XMLParser();
const wxBizMsgCrypt = new WXBizMsgCrypt(token, AESKey, appid); // 会自动解构

rootRouter.post("/",(req,res,next) => {
child_process.execSync(`echo ${JSON.stringify(req.url||"")} and queryStr is: ${JSON.stringify(req.query||"")} \n >> ./request_url.txt`);    
let {signature = '', timestamp = '', nonce = '', echostr = '',msg_signature,encrypt_type, openid} = req.query;
console.info(`\npost request url ${req.url} encrypt type is :${encrypt_type}`);    
console.info(`\npost request params ${req.body.toString()}`);
console.info(`\ncomming post request body:\n ${req.rawBody}`);
console.log('Parsed XML: ' + JSON.stringify(req.body));
    
    if(req.headers["content-type"].includes("xml")){
       console.info("come here");
        let xml = fxp.parse(req.rawBody).xml;
        let shouldEncrypt = false;
        if (encrypt_type === 'aes'){
            xml = wxBizMsgCrypt.DecryptMsg(msg_signature, timestamp, nonce, req.rawBody);
            shouldEncrypt = true;
        }
        console.info("come here1");
        console.info("got xml info to json:"+JSON.stringify(xml));
        let toUser = xml.FromUserName;
        let fromUser = xml.ToUserName;
        let time = moment().unix();
        let msgType = xml.MsgType;
        if(msgType === 'event'){
            //事件
            console.info("got event: "+xml.Event);
            let evt = xml.Event;
            let eventKey = xml.EventKey; 
            let user = xml.FromUserName;
            let list = require("../../public/sub.json").users;
            if(evt === 'subscribe' || evt === 'unsubscribe'){
                if(evt === 'subscribe'){
                    list.push(user);
                }else{
                    list = list.filter((item)=>item !== user);
                }
                let subInfo = {"users":list}
                fs.writeFileSync(`./public/sub.json`,JSON.stringify(subInfo));
                res.end();
            }else if(evt === 'CLICK' && eventKey === 'img_msg'){
                sendImgMsg(res,fromUser,toUser,time,shouldEncrypt);
            }
            else{
                sendTextMsg(res,fromUser,toUser,"Hello"+evt+"事件",time,shouldEncrypt);   
            }
        }else if(msgType === 'scancode_push'){
            sendTextMsg(res,fromUser,toUser,"收到扫码打开页面事件",time,shouldEncrypt);   
        }
        else if(msgType === 'scancode_waitmsg'){
            sendTextMsg(res,fromUser,toUser,"扫码签到成功",time,shouldEncrypt);   
        }else if(msgType === 'location_select'){
            sendTextMsg(res,fromUser,toUser,"定位签到成功",time,shouldEncrypt);   
        }
        else{
            //消息
            console.log("begin sending message to clent");
            sendTextMsg(res,fromUser,toUser,"Hello"+msgType,time,shouldEncrypt);
        }
    }else if(req.headers["content-type"].includes('json')){
        //TODO: if there any json case.
        console.log("content-type is: "+req.headers["content-type"]);
        res.status(200);
        res.send("");
        res.end();
    }
    else{
	console.log("content-type is: "+req.headers["content-type"]);
        res.status(200);
        res.send("");
        res.end();
    }
});

const sendTextMsg = (res,fromUser,toUser,msg="",time, shouldEncrypt)=>{

let _msg = `<xml>
<ToUserName><![CDATA[${toUser}]]></ToUserName>
<FromUserName><![CDATA[${fromUser}]]></FromUserName>
<CreateTime>${time}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${msg}]]></Content>
</xml>`;
if(shouldEncrypt){
    _msg = wxBizMsgCrypt.EncryptMsg({"sReplyMsg":_msg,"sTimeStamp":time})
}
res.status(200);
res.send(_msg)
res.end();
}

const sendImgMsg = (res,fromUser,toUser,time, shouldEncrypt)=>{

    let _msg = `<xml>
        <ToUserName><![CDATA[${toUser}]]></ToUserName>
        <FromUserName><![CDATA[${fromUser}]]></FromUserName>
        <CreateTime>${time}</CreateTime>
        <MsgType><![CDATA[image]]></MsgType>
        <Image>
            <MediaId><![CDATA[uvg9qrlZdTkjl3NJ3tVqpg0fhTZRm9Qt_cbNB7WHFeuPMZ7LynnBEQ0iOzfba_Bz]]></MediaId>
        </Image>
    </xml>`;

    if(shouldEncrypt){
        _msg = wxBizMsgCrypt.EncryptMsg({"sReplyMsg":_msg,"sTimeStamp":time})
    }
    res.status(200);
    res.send(_msg)
    res.end();
    }
    
rootRouter.get("/",(req,res,next) => {
    console.info(`comming get request with query ${JSON.stringify(req.query||"")}`);
    let {signature = '', timestamp = '', nonce = '', echostr = ''} = req.query;
   child_process.execSync(`echo ${JSON.stringify(req.url||"")} and queryStr is: ${JSON.stringify(req.query||"")} \n >> ./request_url.txt`);    
    console.info("get request query string: "+"signature"+signature+"timestamp"+timestamp+"nonce"+nonce+"echostr"+echostr);
    let token = "abcdefg123456789";
    console.log("token str:"+token);

    let str = [token,timestamp,nonce].sort().join('');
    let sha1 = encryption.sha1(str);
    console.log("sha1 str:"+sha1);
    console.log("signature str:"+signature);
    if(sha1 !== signature){
        res.err(new Error("failed"));
    }else{
        res.send(echostr);
    }
    res.end();
});

module.exports = rootRouter;
